import {useState, useEffect, useRef} from 'react'
import {Result} from 'utils/http'

type APIFunc<T, P> = (parameter: P) => Promise<Result<T>>

export interface FetchResult<T> {
  loading: boolean,
  errMsg: string,
  data: T
}

export type API<T, P> = () => {
  api: APIFunc<T, P>,
  data: T,
  cache?: boolean
}

interface FetchState<T> {
  loading: boolean,
  errMsg: string,
  data: T
}

export default function useFetch<T, P>(createApi: API<T, P>, parameter: P) {
  const {api, data} = createApi()
  const parameterRef = useRef(parameter)
  const [result, setResult] = useState<FetchState<T>>({loading: true, errMsg: '', data});
  const {loading} = result;

  useEffect(() => {
    if (loading) {
      api(parameterRef.current).then(res => {
        setResult({
          data: res.data,
          loading: false,
          errMsg: '',
        })
      }).catch(e => {
        setResult({
          errMsg: e.message,
          data,
          loading: false
        })
      })
    }
  }, [loading])

  function setLoading(loading: boolean) {
    setResult({...result, loading})
  }

  return {
    ...result,
    setLoading,
    setParameter: (parameter: P) => {
      parameterRef.current = parameter
      setLoading(true)
    }
  }
}